import os

import click
from flask import Flask

from slewing.blueprints.dev import dev_bp
from slewing.blueprints.user import user_bp
from slewing.extension import db, login_manager
from slewing.models import Dev, User
from slewing.setting import config


def create_app(config_name=None):
    if config_name is None:
        config_name = os.getenv('FLASK_CONFIG', 'development')

    app = Flask('slewing')
    app.config.from_object(config[config_name])

    register_extensions(app)
    register_blueprints(app)
    register_commands(app)
    register_shell_context(app)

    return app


def register_extensions(app):
    db.init_app(app)
    login_manager.init_app(app)


def register_blueprints(app):
    app.register_blueprint(user_bp, url_prefix='/user')
    app.register_blueprint(dev_bp, url_prefix='/device')


def register_commands(app):
    @app.cli.command()
    @click.option('--drop', is_flag=True, help='Create after drop.')
    def initdb(drop):
        """Initialize the database."""
        if drop:
            db.drop_all()
        db.create_all()
        click.echo('Initialized database.')

        dev1 = Dev(mac="F23A94C5A9F0", d1=0.1, d2=0.2, d3=0.3)
        dev2 = Dev(mac="F29C1B7DB427", d1=0.2, d2=0.7, d3=1.2)
        db.session.add(dev1)
        db.session.add(dev2)
        db.session.commit()
        click.echo('Initialized Devices')

    @app.cli.command()
    @click.option('--count', default=20, help='Quantity of messages, default is 20.')
    def forge(count):
        """Generate fake messages."""
        from faker import Faker

        db.drop_all()
        db.create_all()

        fake = Faker('zh_CN')
        click.echo('Working...')

        for i in range(count):
            user = User(
                username=fake.user_name()
            )
            user.set_password(fake.password())
            db.session.add(user)

        db.session.commit()
        click.echo('Created %d fake users.' % count)


def register_shell_context(app):
    @app.shell_context_processor
    def make_shell_context():
        return dict(db=db, Admin=Admin, Post=Post, Category=Category, Comment=Comment)
